package com.lagou.demo;

import com.lagou.mapper.RoleMapper;
import com.lagou.pojo.Role;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

public class MyBatisCacheTest {

    private RoleMapper roleMapper1;
    private RoleMapper roleMapper2;
    private RoleMapper roleMapper3;
    private SqlSession sqlSession1;
    private SqlSession sqlSession2;
    private SqlSession sqlSession3;

    @Before
    public void before() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        sqlSession1 = sqlSessionFactory.openSession(true);
        sqlSession2 = sqlSessionFactory.openSession(true);
        sqlSession3 = sqlSessionFactory.openSession(true);
        roleMapper1 = sqlSession1.getMapper(RoleMapper.class);
        roleMapper2 = sqlSession2.getMapper(RoleMapper.class);
        roleMapper3 = sqlSession3.getMapper(RoleMapper.class);
    }

    @After
    public void after() {
        if (sqlSession1 != null) sqlSession1.close();
        if (sqlSession2 != null) sqlSession2.close();
        if (sqlSession3 != null) sqlSession3.close();
    }

    @Test
    public void oneCache() throws IOException {
        // 一级缓存
        // 第⼀次发起查询⽤户id为1的⽤户信息，先去找缓存中是否有id为1的⽤户信息，如果没有，从数据库查询⽤户信息。得到⽤户信息，将⽤户信息存储到⼀级缓存中。
        Role role1 = roleMapper1.findById(1);
        System.out.println(role1);
        //sqlSession1.clearCache();
        // 第⼆次发起查询⽤户id为1的⽤户信息，先去找缓存中是否有id为1的⽤户信息，缓存中有，直接从缓存中获取⽤户信息
        Role role2 = roleMapper1.findById(1);
        System.out.println(role2);
        // 一级缓存,缓存的是对象
        System.out.println(role1 == role2);
    }

    @Test
    public void oneCacheClear() throws IOException {
        // 一级缓存
        // 第⼀次发起查询⽤户id为1的⽤户信息，先去找缓存中是否有id为1的⽤户信息，如果没有，从数据库查询⽤户信息。得到⽤户信息，将⽤户信息存储到⼀级缓存中。
        // 如果中间sqlSession去执⾏commit操作（执⾏插⼊、更新、删除），则会清空SqlSession中的⼀级缓存，这样做的⽬的为了让缓存中存储的是最新的信息，避免脏读。
        // 第⼆次发起查询⽤户id为1的⽤户信息，先去找缓存中是否有id为1的⽤户信息，缓存中有，直接从缓存中获取⽤户信息
        Role Role = roleMapper1.findById(1);
        System.out.println(Role);
        Role.setRolename("测试数据");
        roleMapper1.update(Role);
        Role = roleMapper1.findById(1);
        System.out.println(Role);
    }

    @Test
    public void twoCache() throws IOException {
        // 二级缓存
        //第⼀次查询，发出sql语句，并将查询的结果放⼊缓存中
        Role Role1 = roleMapper1.findById(1);
        System.out.println(Role1);
        sqlSession1.close(); //第⼀次查询完后关闭 sqlSession
        //第⼆次查询，即使sqlSession1已经关闭了，这次查询依然不发出sql语句
        Role Role2 = roleMapper2.findById(1);
        System.out.println(Role2);
        sqlSession2.close();
        // 一级缓存,缓存的是数据
        System.out.println(Role1 == Role2);
    }

    @Test
    public void twoCacheClear() throws IOException {
        // 二级缓存
        //第⼀次查询，发出sql语句，并将查询的结果放⼊缓存中
        Role u1 = roleMapper1.findById(1);
        System.out.println(u1);
        sqlSession1.close(); //第⼀次查询完后关闭 sqlSession
        //执⾏更新操作，commit()
        u1.setRolename( "aaa" );
        roleMapper3.update(u1);
        sqlSession3.commit();
        //第⼆次查询，由于上次更新操作，缓存数据已经清空(防⽌数据脏读)，这⾥必须再次发出sql语
        Role u2 = roleMapper2.findById(1);
        System.out.println(u2);
        sqlSession2.close();
    }

}
